﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Reflection;
using System.Windows.Controls.Primitives;
using System.Windows.Threading;
using System.Collections.ObjectModel;
using System.Windows.Input;

namespace XWord.WPF.ApplicationFramework.Validations
{
    public abstract partial class Validator : Control
    {
        /// <summary>
        /// Get or set this validation is passed
        /// </summary>
        public bool IsValid
        {
            get { return (bool)GetValue(IsValidProperty); }
            set { SetValue(IsValidProperty, value); }
        }

        public static readonly DependencyProperty IsValidProperty =
            DependencyProperty.Register("IsValid", typeof(bool), typeof(Validator),
            new UIPropertyMetadata(false, new PropertyChangedCallback(IsValidPropertyChanged)));

        private static void IsValidPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            Validator validator = d as Validator;
            validator.ValidPropertyChanged();
        }

        /// <summary>
        ///Get or Set the property's origin element where from
        ///If you set the property's bindingexpression and  Source has the property
        ///Source will be setted automation  This is a dependency property
        /// </summary>
        public FrameworkElement Source
        {
            get { return (FrameworkElement)GetValue(SourceProperty); }
            set { SetValue(SourceProperty, value); }
        }

        public static readonly DependencyProperty SourceProperty =
            DependencyProperty.Register("Source", typeof(FrameworkElement), typeof(Validator),
            new UIPropertyMetadata());

        /// <summary>
        /// 要验证的属性
        /// </summary>
        public object Property
        {
            get { return (object)GetValue(PropertyProperty); }
            set { SetValue(PropertyProperty, value); }
        }

        public static readonly DependencyProperty PropertyProperty =
            DependencyProperty.Register("Property", typeof(object), typeof(Validator),
            new UIPropertyMetadata(new PropertyChangedCallback(ValidPropertyPropertyChanged)));

        /// <summary>
        /// 外部触发的元素
        /// </summary>
        public FrameworkElement TriggerElement
        {
            get { return (FrameworkElement)GetValue(TriggerElementProperty); }
            set { SetValue(TriggerElementProperty, value); }
        }

        public static readonly DependencyProperty TriggerElementProperty =
            DependencyProperty.Register("TriggerElement", typeof(FrameworkElement), typeof(Validator),
            new UIPropertyMetadata(new PropertyChangedCallback(TriggerElementPropertyChanged)));

        public Style ToolTipStyle
        {
            get { return (Style)GetValue(ToolTipStyleProperty); }
            set { SetValue(ToolTipStyleProperty, value); }
        }
        public static readonly DependencyProperty ToolTipStyleProperty =
            DependencyProperty.Register("ToolTipStyle", typeof(Style), typeof(Validator),
            new UIPropertyMetadata(null));


        /// <summary>
        /// Get or set the value which indicate that when validator in current visualtree,validator will do valid on onload event only once
        /// </summary>
        public bool InitializeValidate
        {
            get { return (bool)GetValue(InitializeValidateProperty); }
            set { SetValue(InitializeValidateProperty, value); }
        }

        public static readonly DependencyProperty InitializeValidateProperty =
            DependencyProperty.Register("InitializeValidate", typeof(bool), typeof(Validator),
            new UIPropertyMetadata(false, new PropertyChangedCallback(InitializeValidatePropertyChanged)));

        /// <summary>
        ///Get or set EnableNotSourceContext of an element
        ///When Set false,if Source don't have DataContext,validator will not valid.In case of empty valid.
        ///This is a dependency property
        /// </summary>
        public bool EnableNotSourceContext
        {
            get { return (bool)GetValue(EnableNotSourceContextProperty); }
            set { SetValue(EnableNotSourceContextProperty, value); }
        }

        public static readonly DependencyProperty EnableNotSourceContextProperty =
            DependencyProperty.Register("EnableNotSourceContext", typeof(bool), typeof(Validator),
            new UIPropertyMetadata(true));

        /// <summary>
        /// Get the Error's Collection of Source,This is a dependency property
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static ObservableCollection<PriorityValidationError> GetErrors(DependencyObject obj)
        {
            if (obj.GetValue(ErrorsProperty) == null)
                obj.SetValue(ErrorsProperty, new ObservableCollection<PriorityValidationError>());
            return (ObservableCollection<PriorityValidationError>)obj.GetValue(ErrorsProperty);
        }

        private static readonly DependencyProperty ErrorsProperty =
            DependencyProperty.RegisterAttached("Errors", typeof(ObservableCollection<PriorityValidationError>), typeof(Validator),
            new UIPropertyMetadata(null));

        /// <summary>
        /// Get Validators of the TriggerElement,This is a dependency property
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static List<Validator> GetValidators(DependencyObject obj)
        {
            if(obj.GetValue(ValidatorsProperty)==null)
               obj.SetValue(ValidatorsProperty,new List<Validator>());
            return (List<Validator>)obj.GetValue(ValidatorsProperty);
        }

        public static readonly DependencyProperty ValidatorsProperty =
            DependencyProperty.RegisterAttached("Validators", typeof(List<Validator>), typeof(Validator),
            new UIPropertyMetadata(null));

        /// <summary>
        /// Gets the value of the IsFirstVisit attached property for the specified DependencyObject
        ///When you first change The propery's value,then set IsFirstVisit as mark
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static bool GetIsFirstVisit(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsFirstVisitProperty);
        }

        public static void SetIsFirstVisit(DependencyObject obj, bool value)
        {
            obj.SetValue(IsFirstVisitProperty, value);
        }

        public static readonly DependencyProperty IsFirstVisitProperty =
            DependencyProperty.RegisterAttached("IsFirstVisit", typeof(bool), typeof(Validator),
            new UIPropertyMetadata(true));

        public static TriggerType GetTriggerType(DependencyObject obj)
        {
            return (TriggerType)obj.GetValue(TriggerTypeProperty);
        }

        /// <summary>
        /// Set TriggerElement's type.when set store,triggerElement will not do valid
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="value"></param>
        public static void SetTriggerType(DependencyObject obj, TriggerType value)
        {
            obj.SetValue(TriggerTypeProperty, value);
        }

        public static readonly DependencyProperty TriggerTypeProperty =
            DependencyProperty.RegisterAttached("TriggerType", typeof(TriggerType), typeof(Validator),
            new UIPropertyMetadata(TriggerType.Trigger, TriggerTypePropertyChanged));

        public static object GetValidateTarget(DependencyObject obj)
        {
            return (object)obj.GetValue(ValidateTargetProperty);
        }

        public static void SetValidateTarget(DependencyObject obj, object value)
        {
            obj.SetValue(ValidateTargetProperty, value);
        }

        public static readonly DependencyProperty ValidateTargetProperty =
            DependencyProperty.RegisterAttached("ValidateTarget", typeof(object), typeof(Validator),
            new UIPropertyMetadata(new PropertyChangedCallback(OnValidateTargetPropertyChanged)));

    }

    public enum TriggerType
    {
        Trigger,
        Store
    }
}
